#include <types.h>
#include <sys_config.h>
#include <retcode.h>
#include <api/libc/string.h>
#include <api/libc/printf.h>
#include <osal/osal.h>
#include <api/libmp/pe.h>
#include "image_engine.h"
#include "plugin.h"

#ifdef DUAL_ENABLE
#include <modules.h>

#define COMMON_FUNCTIONS    // for dual-cpu remote call
char* mp_flush_file_name(char *file)
{
    osal_cache_flush(file, STRLEN(file)+1);
    if(file[STRLEN(file)-1] != *(volatile unsigned char*)((UINT32)(file+STRLEN(file)-1)|0xa0000000))
    {
        //make sure data is flushed into cache before send to SEE
        ASSERT(0);
    }
    //pass uncache address to SEE to make sure SEE read correct filename
    //it seems SEE invalidate cache has problem???
    file = (char *)((UINT32)(file)|0xa0000000);
    return file;
}

char* mp_flush_key_file(char *file)
{
    osal_cache_flush(file, STRLEN(file)+1);
    
    //pass uncache address to SEE to make sure SEE read correct filename
    //it seems SEE invalidate cache has problem???
    file = (char *)((UINT32)(file)|0xa0000000);
    return file;
}



enum MUSIC_ENGINE_FUNC{
    FUNC_IMAGE_ENGINE_INIT = 0,   
    FUNC_IMAGE_ENGINE_CLEANUP,
    FUNC_IMAGE_ENGINE_ROTATE,
    FUNC_IMAGE_ENGINE_DECODE,
    FUNC_IMAGE_ENGINE_SHOW,
    FUNC_IMAGE_ENGINE_ABORT,
    FUNC_IMAGE_ENGINE_ZOOM,
    FUNC_IMAGE_ENGINE_GET_INFO,
    FUNC_IMAGE_ENGINE_IO_CONTROL,
    FUNC_IMAGE_ENGINE_SWAP,
    FUNC_IMAGE_ENGINE_OPTION,
    FUNC_IMAGE_ENGINE_PARA,
    FUNC_IMAGE_ENGINE_INIT_NETWORK,
    FUNC_IMAGE_ENGINE_DECODE_NETWORK,
};

#ifndef _LIB_PE_IMAGE_ENGINE_REMOTE

int image_engine_init(struct pe_image_cfg *pe_image_cfg);
int image_engine_cleanup();
int image_engine_rotate(unsigned char rotate_angle);
int image_engine_decode(char *filename, struct image_config *cfg);
int image_engine_show();
int image_engine_abort();
int image_engine_zoom(struct Rect *dstRect, struct Rect *srcRect);
int image_engine_get_info(char *filename, struct image_info *info);
BOOL imagedec_ioctl(imagedec_id id,UINT32 cmd, UINT32 para);
int image_engine_2d_to_3d_swap(int type);
int image_engine_3d_user_option(struct image_3d_para *para);
int image_engine_set_disp_param(int display_type, struct image_3d_para *para);
int image_engine_init_network(UINT32 file_addr, UINT32 file_len, struct pe_image_cfg *pe_image_cfg);
int image_engine_decode_network(char *filename, struct image_config *cfg);



UINT32 image_engine_entry[] = 
{
    (UINT32)image_engine_init,
    (UINT32)image_engine_cleanup,
    (UINT32)image_engine_rotate,
    (UINT32)image_engine_decode,
    (UINT32)image_engine_show,
    (UINT32)image_engine_abort,
    (UINT32)image_engine_zoom,
    (UINT32)image_engine_get_info,
    (UINT32)imagedec_ioctl,
    (UINT32)image_engine_2d_to_3d_swap,
    (UINT32)image_engine_3d_user_option,
    (UINT32)image_engine_set_disp_param,
    (UINT32)image_engine_init_network,
    (UINT32)image_engine_decode_network,
};

void lib_pe_image_engine_callee(UINT8 *msg)
{
    OS_hld_callee(image_engine_entry, msg);
}

#endif

#ifdef _LIB_PE_IMAGE_ENGINE_REMOTE
#undef offsetof
#define offsetof(type, f) ((unsigned long) \
((char *)&((type *)0)->f - (char *)(type *)0))

typedef struct Imagedec_frm_t
{
	UINT8 *frm_y_addr;
	UINT32 frm_y_len;
	UINT8 *frm_c_addr;
	UINT32 frm_c_len;
	UINT32 busy;
}Imagedec_frm,*pImagedec_frm;

static UINT32 desc_ie_init[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(struct pe_image_cfg)), 
  1, DESC_P_PARA(0, 0, 0),
  //desc of pointer ret
  0,                          
  0,
};

static UINT32 desc_img_display[] =
{//desc of pointer para
   2, DESC_STATIC_STRU(0, sizeof(struct image_display_t)), DESC_STATIC_STRU(1, sizeof(struct image_slideshow_effect)),
   2, DESC_P_PARA(0, 1, 0), DESC_P_STRU(1, 0, 1, offsetof(struct image_display_t, effect)),
   //desc of pointer ret
   0,
   0,
};

static UINT32 desc_ie_decode[] = 
{ //desc of pointer para
  2, DESC_STATIC_STRU(0, sizeof(struct image_config)), DESC_STATIC_STRU(1, sizeof(struct image_slideshow_effect)), 
  2, DESC_P_PARA(0, 1, 0), DESC_P_STRU(1, 0, 1, offsetof(struct image_config, effect)),
  //desc of pointer ret
  0,                          
  0,
};


static UINT32 desc_ie_zoom[] = 
{ //desc of pointer para
  2, DESC_STATIC_STRU(0, sizeof(struct Rect)), DESC_STATIC_STRU(1, sizeof(struct Rect)), 
  2, DESC_P_PARA(0, 0, 0), DESC_P_PARA(1, 1, 1),
  //desc of pointer ret
  0,                          
  0,
};

static UINT32 desc_ie_get_info[] = 
{ //desc of pointer para
  1, DESC_OUTPUT_STRU(0, sizeof(struct image_info)),  
  1, DESC_P_PARA(0, 1, 0),
  //desc of pointer ret
  0,                          
  0,
};

static UINT32 desc_ie_ioctrl_cfg_deo_frm[] = 
{ //desc of pointer para
  1, DESC_STATIC_STRU(0, sizeof(Imagedec_frm)), 
  1, DESC_P_PARA(0, 2, 0),
  //desc of pointer ret
  0,                          
  0,
};

extern struct img_callback g_img_cb;
int image_engine_init(struct pe_image_cfg *pe_image_cfg)
{
    g_img_cb.mp_cb = pe_image_cfg->mp_cb;
    jump_to_func(NULL, OS_hld_caller, pe_image_cfg, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(1<<16)|FUNC_IMAGE_ENGINE_INIT, desc_ie_init);
}

int image_engine_cleanup()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(0<<16)|FUNC_IMAGE_ENGINE_CLEANUP, NULL);
}

int image_engine_rotate(unsigned char rotate_angle)
{
    jump_to_func(NULL, OS_hld_caller, rotate_angle, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(1<<16)|FUNC_IMAGE_ENGINE_ROTATE, NULL);
}

static int image_engine_display_naked(char *filename, struct image_display_t *img_desc)
{
    jump_to_func(NULL, OS_hld_caller, filename, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(2<<16)|FUNC_IMAGE_ENGINE_DECODE, NULL);
}

static int image_engine_decode_naked(char *filename, struct image_config *cfg)
{
    jump_to_func(NULL, OS_hld_caller, filename, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(2<<16)|FUNC_IMAGE_ENGINE_DECODE, desc_ie_decode);
}

int image_engine_decode(char *filename, struct image_config *cfg)
{
    filename = mp_flush_file_name(filename);
    if (3 == strlen(filename)  && !strcasecmp(filename, "YUV")) 
    {
    	struct image_display_t *img_dpy = (struct image_display_t *)cfg;
	return image_engine_display_naked( filename, img_dpy);
    }
    return image_engine_decode_naked(filename, cfg);
}

int image_engine_show()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(0<<16)|FUNC_IMAGE_ENGINE_SHOW, NULL);
}

int image_engine_abort()
{
    jump_to_func(NULL, OS_hld_caller, null, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(0<<16)|FUNC_IMAGE_ENGINE_ABORT, NULL);
}

int image_engine_zoom(struct Rect *dstRect, struct Rect *srcRect)
{
    jump_to_func(NULL, OS_hld_caller, dstRect, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(2<<16)|FUNC_IMAGE_ENGINE_ZOOM, desc_ie_zoom);
}

static int image_engine_get_info_naked(char *filename, struct image_info *info)
{
    jump_to_func(NULL, OS_hld_caller, filename, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(2<<16)|FUNC_IMAGE_ENGINE_GET_INFO, desc_ie_get_info);
}

int image_engine_get_info(char *filename, struct image_info *info)
{
    filename = mp_flush_file_name(filename);
    return image_engine_get_info_naked(filename, info);
}

BOOL imagedec_ioctl(imagedec_id id,UINT32 cmd, UINT32 para)
{
    UINT32 *desc = NULL;

    switch(cmd)
	{
		case IMAGEDEC_IO_CMD_OPEN_HW_ACCE:
		case IMAGEDEC_IO_CMD_FILL_LOGO:
		case IMAGEDEC_IO_CMD_CLEAN_FRM:
        case IMAGEDEC_IO_CMD_NEED_LOGO:
        default:
            desc = NULL;
			break;
		
		case IMAGEDEC_IO_CMD_CFG_DEO_FRM:
            desc = desc_ie_ioctrl_cfg_deo_frm;
			break;
	}
    
    jump_to_func(NULL, OS_hld_caller, id, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(3<<16)|FUNC_IMAGE_ENGINE_IO_CONTROL, desc);
}

int image_engine_2d_to_3d_swap(int type)
{
    jump_to_func(NULL, OS_hld_caller, type, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(1<<16)|FUNC_IMAGE_ENGINE_SWAP, NULL);
}

int image_engine_3d_user_option(struct image_3d_para *para)
{
    jump_to_func(NULL, OS_hld_caller, para, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(1<<16)|FUNC_IMAGE_ENGINE_OPTION, NULL);
}

int image_engine_set_disp_param(int display_type, struct image_3d_para *para)
{
    jump_to_func(NULL, OS_hld_caller, display_type, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(2<<16)|FUNC_IMAGE_ENGINE_PARA, NULL);
}

int image_engine_init_network(UINT32 file_addr, UINT32 file_len, struct pe_image_cfg *pe_image_cfg)
{
    UINT32 desc[] =
    { //desc of pointer para
       1, DESC_STATIC_STRU(0, sizeof(struct pe_image_cfg)),
       1, DESC_P_PARA(0, 2, 0),
       //desc of pointer ret
       0,
       0,
    };
    jump_to_func(NULL, OS_hld_caller, file_addr, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(3<<16)|FUNC_IMAGE_ENGINE_INIT_NETWORK, desc);
}

int image_engine_decode_network(char *filename, struct image_config *cfg)
{
    jump_to_func(NULL, OS_hld_caller, filename, (LIB_PE_IMAGE_ENGINE_MODULE<<24)|(2<<16)|FUNC_IMAGE_ENGINE_DECODE_NETWORK, desc_ie_decode);
}

#endif

#endif

